const store = Vuex.createStore({
  plugins: [window.createPersistedState()],
  state() {
    return {
      language: 'cn', // en cn hk kr ja
      resDomain: 'https://tenvix.meow42.cn/',
      apiDomain: 'https://d3hh2hbrt6a9v.cfc-execute.gz.baidubce.com/',
      activedView: 'action', // overview avater action option
      res: {
        bd: { code: '00002', data: {} },
        hd: { code: '00176', data: {} },
        cp: { code: '01771', data: {} }, //01788
        hr: { code: '01978', data: {} },
        fc: { code: '00136', data: {} }, //00007
        fa: { code: '02500', data: {} }, //00056
        cl: { code: '00095', data: {} }, //01793
        wp: { code: '02540', data: {} }, //00804
        emo: { code: '', data: {} },
        dfA: { code: '00008', data: {} },
        doA: { code: '20021', data: {} },
        amA: { code: '24617', data: {} },
        dcA: { code: '25021', data: {} },
        lpA: { code: '21521', data: {} },
        ppA: { code: '22000', data: {} },
        rhA: { code: '22515', data: {} },
        lhA: { code: '23002', data: {} },
        rhlhA: { code: '', data: {} },
        dfS: { code: '00010', data: {} },
        doS: { code: '20002', data: {} },
        amS: { code: '20502', data: {} },
        dcS: { code: '21020', data: {} },
        lpS: { code: '21502', data: {} },
        ppS: { code: '22002', data: {} },
        rhS: { code: '22508', data: {} },
        lhS: { code: '23029', data: {} },
        rhlhS: { code: '', data: {} },
        dfT: { code: '00009', data: {} },
        doT: { code: '20001', data: {} },
        amT: { code: '20501', data: {} },
        dcT: { code: '21001', data: {} },
        lpT: { code: '21501', data: {} },
        ppT: { code: '22001', data: {} },
        rhT: { code: '22506', data: {} },
        lhT: { code: '23000', data: {} },
        rhlhT: { code: '', data: {} },
        vehicle: { code: '', data: {} },
      },
      act: {
        body: { name: 'stand1_0_body', list: [] },
        arm: { name: 'stand1_0_arm', list: [] },
        leg: { name: '', list: [] },
        clothes: { name: 'stand1_0_body', list: [] },
        sleeve: { name: 'stand1_0_arm', list: [] },
        pants: { name: '', list: [] },
        wing: { name: '', list: [] },
        head: { name: 'head0', list: [] },
        face: { name: 'face_normal', list: [] },
        horn: { name: '', list: [] },
        horn1: { name: '', list: [] },
        ear: { name: '', list: [] },
        ear1: { name: '', list: [] },
        facial: { name: 'faCenter', list: [] }, //faCenter
        facial1: { name: '', list: [] },
        hair: { name: 'hairTopLeft_a', list: [] },
        hair1: { name: '', list: [] },
        cap: { name: 'capLeft', list: [] }, //capLeft
        weapon: { name: 'run_01', list: [] }, //wp00
        emotion: { name: '', list: [] },
        'a-body': { name: 'body_stand1_0', list: [] },
        'a-arml': { name: 'arml_001', list: [] },
        'a-armr': { name: 'armr_002', list: [] },
        'a-arms': { name: '', list: [] },
        'a-legl': { name: 'legl_001', list: [] },
        'a-legr': { name: 'legr_002', list: [] },
        'a-door': { name: 'door01', list: [] },
        'a-door1': { name: 'doorback01', list: [] },
        'a-armor': { name: 'bodyarmor02', list: [] },
        'a-skirt': { name: 'skirt00', list: [] },
        'a-booster': { name: 'booster00', list: [] },
        'a-arml1': { name: 'arml_001', list: [] },
        'a-armr1': { name: 'armr_002', list: [] },
        'a-legl1': { name: 'legl_001', list: [] },
        'a-legr1': { name: 'legr_002', list: [] },
        'a-propulsion': { name: 'pp00', list: [] },
        'a-weapon': { name: 'g_stand1_00', list: [] },
        'a-weapon1': { name: 'g_stand1_01_00', list: [] },
        'a-shield': { name: 'shield00', list: [] },
        's-body': { name: 'body_gstand1_00', list: [] },
        's-head': { name: 'head00', list: [] },
        's-eye': { name: 'eye00', list: [] },
        's-fleg': { name: 'g_fleg00', list: [] },
        's-bleg': { name: 'g_bleg00', list: [] },
        's-tleg': { name: '', list: [] },
        's-cap': { name: 'head00', list: [] },
        's-armor': { name: 'g_stand1_00', list: [] },
        's-foot1': { name: 'fl_gstand1_00', list: [] },
        's-foot2': { name: 'bl_gstand1_00', list: [] },
        's-tail': { name: 'tail_gstand1_00', list: [] },
        's-wing1': { name: 'w_ground_00', list: [] },
        's-wing2': { name: 'wb_ground_00', list: [] },
        's-weapon': { name: '', list: [] },
        's-book': { name: '', list: [] },
        't-body': { name: 'g_stand_00_bd', list: [] },
        't-head': { name: 'head00', list: [] },
        't-arml': { name: 'arml00', list: [] },
        't-armr': { name: 'armr00', list: [] },
        't-leg': { name: 'leg00', list: [] },
        't-head1': { name: 'head00', list: [] },
        't-body1': { name: 'g_stand_00_bd', list: [] },
        't-arml1': { name: 'arml00', list: [] },
        't-armr1': { name: 'armr00', list: [] },
        't-legb': { name: 'leg00', list: [] },
        't-arml2': { name: 'arml00', list: [] },
        't-armr2': { name: 'armr00', list: [] },
        't-legl': { name: 'g_stand_00_bdl', list: [] },
        't-legr': { name: 'g_stand_00_bdr', list: [] },
        't-cloak': { name: 'g_stand_00_bd', list: [] },
        't-waeponrf': { name: 'rf_gstand1_00', list: [] },
        't-waeponrb': { name: 'rb_gstand1_00', list: [] },
        't-waeponlf': { name: 'lf_stand1_00', list: [] },
        't-waeponlb': { name: 'lb_stand1_00', list: [] },
        //other: { name: '', list: [] },
      },
      order: [], // 部件对象排序
      pilot: {
        race: 'andras', // andras, silva, talli
        skin: 'yellow', // yellow, white, brown
        sex: 'none', // none, male, female
      },
      guard: {
        race: 'andras', // andras, silva, talli
      },
      frameNote: {}, // 动作帧备注名称
      option: {
        avatarListMode: 'group', // none, asc, group
        avatarSelectionTips: 'raw', // none, preview, raw
        canvasBackground: 'none', // none, axis
        showFrameNote: true, // 是否显示动作帧备注文本
        hideImage: false, // 是否显示图像（用于测试）
      },
      user: {
        id: '',
        name: '',
      },
      tCanvas: undefined, // 公共canvas元素的包装对象
    }
  },
  getters: {
    /** 获取多语言文本 */
    i18n: (state) => (key) => {
      return (I18N && I18N[key]) ? I18N[key][state.language] || I18N[key]['en'] : '';
    },
    /** 获取XML资源的URL */
    resXmlUrl: (state) => (code) => {
      return state.resDomain + 'item/' + code + '.xml';
    },
    /** 获取png资源的URL */
    resPngUrl: (state) => (name) => {
      return state.resDomain + 'item/' + name + '_0.png';
    },
    /** 获取icon资源的URL */
    resIconUrl: (state) => (code) => {
      console.log(code);
      if (state.option.hideImage) return '';
      if (code === '00000' || code === '') return '';
      console.log(code);
      return state.resDomain + 'item/' + code + '_icon.png';
    },
    /** 获取公共canvas */
    tCanvas: (state) => {
      return document.getElementById(statet.CanvasId)
    },
  },
  mutations: {
    /** 变更视图 */
    changeView(state, value) {
      if (value) state.activedView = value;
    },
    /** 变更部件的动作帧 */
    setActFrame(state, payload = { part: '', name: '' }) {
      let key = payload['part'];
      if (!key) return;
      state.act[key].name = payload['name'];
      //console.log('setActFrame', payload);
    },
    /** 设置守护者类型 */
    setGuardType(state, value) {
      if (['andras', 'silva', 'talli'].includes(value)) {
        state.guard.type = value;
      }
    },
    /** 变更全局设置选项 */
    setOption(state, payload) {
      console.log('setOption', payload);
      if (!payload['key']) return;
      state.option[payload['key']] = payload['value'] || '';
    },
    /** 变更用户信息 */
    setUserInfo(state, payload) {
      if (payload['id'] && payload['name']) {
        state.user.id = payload['id'];
        state.user.name = payload['name'];
      } else {
        state.user.id = '';
        state.user.name = '';
      }
    },
    /** 设置动作帧描述对象 */
    setFrameNote(state, json) {
      //console.log('setOption', payload);
      state.frameNote = json || {};
    },
    /** 初始化动作部件的基本属性和link关系 */
    initActItem(state) {
      // 填充组件
      for(let key in state.act){
        let _part = Tenvi.part[key];
        if (!_part) return;
        let part = state.act[key];
        Object.assign(part, _part); // 合并部件定义中的属性
        part['root'] = state.act[_part.root]; // 映射实际的根节点对象
        // 增加设置当前帧数据的方法
        part['setData'] = () => {
          part.data = state.res[part.res]['data'][part.name];
        };
        // 增加绘制坐标获取方法，递归到根节点
        part['getDrawPoint'] = () => {
          if (!part.root || part.root === 'none') {
            return { x: -part.data.centerX, y: part.data.centerY };
          }
          if (!part.data) return { x: 0, y: 0 };
          
          let rlp = part.root.data.point[part.link]; // 根组件的连接点坐标
          if (!rlp) return { x: 0, y: 0 }; // 根组件上可能并不存在对应连接点

          let rp = part.root.getDrawPoint(); // 根组件坐标
          let lp = part.data.point[part.link]; // 连接点坐标
          return { x: rp.x + rlp.x - lp.x, y: rp.y - rlp.y + lp.y };
        };
      }
      // 进行排序
      state.order = [];
      Tenvi.order.reverse().map(key => {
        if (!state.act[key]) return;
        state.act[key].key = key; // 追加key属性
        state.order.push(state.act[key]);
      });
      //console.log('store.mutations.initActPart', state.act);
    },
    /** 初始化资源对象的基本属性 */
    initResItem(state) {
      // 追加资源与部件之前的关联关系
      for (let key in Tenvi.part) {
        if (!state.act[key]) continue; // store中必须存在动作部件
        let resKey = Tenvi.part[key]['res'];
        if (!state.res[resKey]) continue; // store中必须存在资源类型
        if (!state.res[resKey]['links']) state.res[resKey]['links'] = {};
        state.res[resKey]['links'][key] = Tenvi.part[key]['regex'] || /.*/;
      }
      console.log('initResItem', state.res);
    },
    /** 初始化公共画布 */
    initCanvas(state, id) {
      let canvas = document.getElementById(id);
      state.tCanvas = new TenviCanvas(canvas);
    },
    /** 装填动作帧名称列表 */
    loadActList(state, payload = { key: '', data: {} }) {
      let resKey = payload['key'];
      let resData = payload['data'];
      let resLinks = state.res[resKey]['links'];
      if (!resLinks) return;
      // 初始化list
      for (let actKey in resLinks) {
        state.act[actKey].list = [];
      }
      // 填装list
      for (let frameKey in resData) {
        for (let actKey in resLinks) {
          if (resLinks[actKey].test(frameKey)) {
            state.act[actKey].list.push(frameKey);
          }
        }
      }
      return;
    }
  },
  actions: {
    /** 变更语言 */
    changeLanguage({ dispatch, commit, state, getters }, value) {
      if (!value) return;
      state.language = value;
      document.title = getters.i18n('app-title');
    },
    /** 远程加载文件 payload: { url: '', type: 'xml' | 'json' }*/
    async loadFile({ dispatch, commit, state, getters }, payload) {
      return new Promise((resolve, reject) => {
        if (!payload || !payload['url']) reject();
        const xhr = new XMLHttpRequest();
        // 请求成功
        xhr.onload = e => {
          //console.log('request success:', xhr);
          if (!payload['type']) resolve(xhr.response);
          if (payload['type'] === 'xml') resolve(xhr.responseXML);
          if (payload['type'] === 'json') resolve(JSON.parse(xhr.response));
          resolve(xhr.response);
        };
        // 请求失败
        xhr.onerror = e => {
          console.error('request error:', e);
          reject();
        };
        // 请求超时
        xhr.ontimeout = e => {
          console.info('request timeout:', e);
          reject();
        };
        xhr.timeout = 42000;
        xhr.open('GET', payload.url, true);
        xhr.send();
     });
    },
    /** 设置资源 payload: { key: '', code: '', data: {} } */
    async setRes({ dispatch, commit, state, getters }, payload) {
      //console.log('setRes', payload);
      let key = payload['key'];
      if (!key || !state.res[key]) return;
      let item = state.res[key];
      item.code = payload['code'] || '';
      if (payload['data']) {
        item.data = payload['data'];
        return;
      }
      // 远程加载数据
      item.data = {};
      if (item.code.length < 1) return;
      let url = getters.resXmlUrl(item.code);
      await dispatch('loadFile', { url: url, type: 'xml'})
        .then( xml => {
          let payload = { domain: state.resDomain + 'item/', suffix: '.png' };
          item.data = Tenvi.xml2json(xml, payload).frame;
          // 装填动作帧名称列表
          commit('loadActList', { key: key, data: item.data });
          //console.log('setRes => ok', item.data);
        });
      return true;
    },
    /** 资源重新载入 */
    reloadRes({ dispatch, commit, state, getters }, payload) {
      for(let key in state.res) {
        let code = state.res[key]['code'];
        dispatch('setRes', { key: key, code: code });
      }
    },
    /** 设置角色种族 */
    setPilotRace({ dispatch, commit, state, getters }, value) {
      if (['andras', 'silva', 'talli'].includes(value)) {
        state.pilot.race = value;
        dispatch('setPilotSkin', state.pilot.skin); // 触发皮肤素材资源变更
      }
    },
    /** 设置角色皮肤 */
    setPilotSkin({ dispatch, commit, state, getters }, value) {
      let skinIndex = ['yellow', 'white', 'brown'].indexOf(value);
      if (skinIndex < 0) return;
      state.pilot.skin = value;
      let bdCode = Tenvi.res.bd;
      dispatch('setRes', { key: 'bd', code: bdCode[skinIndex] });
      // 头部素材联动
      let hdCode = Tenvi.res.hd[state.pilot.race];
      dispatch('setRes', { key: 'hd', code: hdCode[skinIndex] });
    },
    /** 加载image对象 */
    async loadImage({ dispatch, commit, state, getters }, url) {
      return new Promise((resolve, reject) => {
        let img = new Image();
        img.setAttribute("crossOrigin",'Anonymous'); // 设置允许跨域，避免污染canvas导致无法输出
        img.onload = () => {
          //console.log(img.src, "is loaded");
          resolve(img);
        };
        img.src = url;
      });
    },
    /** 装载绘制所需资源 */
    async loadDrawRes({ dispatch, commit, state, getters }, payload = { mode: 'past', excludes: [] }) {
      // 装载当前frame的数据
      for (let key in state.act) {
        state.act[key].setData();
      }
      //console.log('loadDrawRes - start', state.order);
      // 根据图层顺序填充数据组
      let result = [];
      for (let i = 0; i < state.order.length; i++) {
        let part = state.order[i]; // order[i]指向act中的对象
        if (!part.name) continue; // 跳过动作帧为空的部件
        if (payload['mode'] && payload.mode.indexOf(part.type) === -1) continue; // 按类型过滤部件
        if (payload['excludes'] && payload.excludes.indexOf(part.key) > -1) continue; // 按名称过滤部件 
        //console.log('loadDrawRes:', part.res, part.name);
        let data = {};
        data.name = part.name;
        data.point = part.getDrawPoint();
        if (!part['data']) continue;
        data.size = { x: part.data.sizeX, y: part.data.sizeY };
        data.offset = { x: part.data.offsetX, y: part.data.offsetY };
        data.url = part.data.imgURL;
        data.img = await dispatch('loadImage', data.url);
        data.opacity = part.data['hide'] ? 0 : 1; // 不透明度
        result.push(data);
      }
      console.log('loadDrawRes - end', result);
      // 载入图像资源
      return new Promise((resolve, reject) => {
        resolve(result);
      });
    },
    /** 远程加载动作帧备注 */
    async loadFrameNote({ dispatch, commit, state, getters }, url) {
      console.log('loadFrameNotes', url);
      if (!url) return this;
      if (url === 'none') commit('setFrameNote', {}); // 清空数据的方法
      await dispatch('loadFile', { url: url, type: 'json' })
        .then( json => {
          commit('setFrameNote', json);
          console.log('loadFrameNotes => ok', json);
        });
      return this;
    },
  }
});